home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <ctype.h>
- #include <string.h>
- #include <stdlib.h>
- #include <math.h>
- #include "proto.h"
- #include "parwave.h"
- #include "elements.h"
- #include "darray.h"
- #include "holmes.h"
- #include "getargs.h"
-
- FILE *par_file;
- int speed = 1;
-
- double frac = 1.0;
-
- typedef struct
- {
- float v; /* boundary value */
- int t; /* transition time */
- }
- slope_t;
-
- typedef struct
- {
- slope_t p[nEparm];
- } trans_t;
-
- typedef struct
- {float a;
- float b;
- float v;
- } filter_t, *filter_ptr;
-
- static float filter PROTO((filter_ptr p,float v));
-
- static float filter(p,v)
- filter_ptr p;
- float v;
- {
- return p->v = (p->a * v + p->b * p->v);
- }
-
- /* 'a' is dominant element, 'b' is dominated
- ext is flag to say to use external times from 'a' rather
- than internal i.e. ext != 0 if 'a' is NOT current element.
-
- */
-
- static void set_trans PROTO((slope_t * t, Elm_ptr a, Elm_ptr b, int ext, char e));
-
- static void
- set_trans(t, a, b, ext, e)
- slope_t *t;
- Elm_ptr a;
- Elm_ptr b;
- int ext;
- char e;
- {int i;
- for (i=0; i < nEparm; i++)
- {
- t[i].t = ((ext) ? a->p[i].ed : a->p[i].id)*speed;
- if (t[i].t)
- t[i].v = a->p[i].fixd + (a->p[i].prop * b->p[i].stdy) * 0.01;
- else
- t[i].v = b->p[i].stdy;
- }
- }
-
- static float linear PROTO((Elm_ptr em, char *p, float a, float b, int t, int d));
-
- static float
- linear(em, p, a, b, t, d)
- Elm_ptr em;
- char *p;
- float a;
- float b;
- int t;
- int d;
- {
- float r = a;
- float f = 0.0;
- if (t > 0)
- {
- f = (float) t / (float) d;
- r += (b - a) * f;
- }
- #ifdef DEBUG
- printf("%4s %s = %g %g\n", em->name, p, r, f);
- #endif
- return r;
- }
-
- static float interpolate PROTO((Elm_ptr em, char *p, slope_t * s, slope_t * e, float mid, int t, int d));
-
- static float
- interpolate(em, p, s, e, mid, t, d)
- Elm_ptr em;
- char *p;
- slope_t *s;
- slope_t *e;
- float mid;
- int t;
- int d;
- {
- float steady = d - (s->t + e->t);
- #ifdef DEBUG
- fprintf(stdout, "%4s %s s=%g,%d e=%g,%d m=%g,%g\n",
- em->name, p, s->v, s->t, e->v, e->t, mid, steady);
- #endif
- if (steady >= 0)
- {
- /* Value reaches stready state somewhere ... */
- if (t < s->t)
- return linear(em, p, s->v, mid, t, s->t); /* initial transition */
- else
- {
- t -= s->t;
- if (t <= steady)
- return linear(em, p, mid, mid, 0, d); /* steady state */
- else
- return linear(em, p, mid, e->v, (int) (t - steady), e->t); /* final transition */
- }
- }
- else
- {
- /* Does not make it to steady state - do trajectories intersect ? */
- if (s->t == 0)
- steady = 0; /* initial is vertical */
- else if (e->t == 0)
- steady = d; /* final is vertical */
- else
- {
- float ms = (mid - s->v) / s->t;
- float me = (e->v - mid) / e->t;
- if (me == ms || (steady = (s->v - e->v + me * d) / (me - ms)) < 0 || steady > d)
- return linear(em, p, s->v, e->v, t, d);
- /* do not intersect in range */
- }
- if (t < steady)
- return linear(em, p, s->v, mid, t, s->t); /* initial transition */
- else
- return linear(em, p, e->v, mid, d - t, e->t); /* final transition */
- }
- }
-
- unsigned
- holmes(nelm, elm, nsamp, samp_base)
- unsigned nelm;
- unsigned char *elm;
- unsigned nsamp;
- short *samp_base;
- {
- filter_t flt[nEparm];
- klatt_t pars;
- short *samp = samp_base;
- Elm_ptr le = &Elements[0];
- unsigned i = 0;
- int j;
- pars = def_pars;
- pars.B1phz = pars.B1hz = 60;
- pars.B2phz = pars.B2hz = 90;
- pars.B3phz = pars.B3hz = 150;
- pars.F0hz10 = def_pars.F0hz10;
- pars.FNPhz = le->p[fn].stdy;
- #if 0
- pars.F4hz = 3500;
- #endif
- pars.B4phz = def_pars.B4phz;
- /* flag new utterance */
- initsw = 0;
- for (j=0; j < nEparm; j++)
- {
- flt[j].v = le->p[j].stdy;
- flt[j].a = frac;
- flt[j].b = 1.0-frac;
- }
- while (i < nelm)
- {
- Elm_ptr ce = &Elements[elm[i++]];
- unsigned dur = ce->du * speed;
- /* Skip zero length elements which are only there to affect
- boundary values of adjacent elements
- */
- if (dur > 0)
- {
- Elm_ptr ne = (i < nelm) ? &Elements[elm[i]] : &Elements[0];
- slope_t start[nEparm];
- slope_t end[nEparm];
- unsigned t;
-
- if (ce->rk > le->rk)
- {
- if (par_file)
- fprintf(par_file,"# %s < %s\n",le->name,ce->name);
- set_trans(start, ce, le, 0, 's'); /* we dominate last */
- }
- else
- {
- if (par_file)
- fprintf(par_file,"# %s >= %s\n",le->name,ce->name);
- set_trans(start, le, ce, 1, 's'); /* last dominates us */
- }
-
- if (ne->rk > ce->rk)
- {
- if (par_file)
- fprintf(par_file,"# %s < %s\n",ce->name,ne->name);
- set_trans(end, ne, ce, 1, 'e'); /* next dominates us */
- }
- else
- {
- if (par_file)
- fprintf(par_file,"# %s >= %s\n",ce->name,ne->name);
- set_trans(end, ce, ne, 0, 'e'); /* we dominate next */
- }
-
- if (par_file)
- {int j;
- fprintf(par_file,"# %s\n",ce->name);
- for (j=0; j < nEparm; j++)
- fprintf(par_file,"%c%6s",(j) ? ' ' : '#',Ep_name[j]);
- fprintf(par_file,"\n");
- for (j=0; j < nEparm; j++)
- fprintf(par_file,"%c%6.4g",(j) ? ' ' : '#',start[j].v);
- fprintf(par_file,"\n");
- for (j=0; j < nEparm; j++)
- fprintf(par_file,"%c%6d",(j) ? ' ' : '#',start[j].t);
- fprintf(par_file,"\n");
- }
-
- for (t = 0; t < dur; t++)
- {
- float tp[nEparm];
- int j;
- for (j=0; j < nEparm; j++)
- tp[j] = filter(flt+j,interpolate(ce, Ep_name[j], &start[j], &end[j], (float) ce->p[j].stdy, t, dur));
-
- /* Now call the synth for each frame */
- pars.AVdb = pars.AVpdb = tp[av];
- pars.AF = tp[af];
- /*
- pars.ANP = 14 + tp[an];
- */
- pars.FNZhz = tp[fn];
- pars.ASP = tp[asp];
- pars.Aturb = tp[avc];
- pars.B1phz = pars.B1hz = tp[b1];
- pars.B2phz = pars.B2hz = tp[b2];
- pars.B3phz = pars.B3hz = tp[b3];
- pars.AB = 14 + tp[ab];
- pars.A5 = 14 + tp[a5];
- pars.A6 = 14 + tp[a6];
- pars.F1hz = tp[f1];
- pars.F2hz = tp[f2];
- pars.F3hz = tp[f3];
- /* 14 + is a bodge to get amplitudes up to klatt-compatible levels
- Needs to be fixed properly in tables
- */
- pars.A1 = 14 + tp[a1];
- pars.A2 = 14 + tp[a2];
- pars.A3 = 14 + tp[a3];
- pars.A4 = 14 + tp[a4];
- parwav(&pars, samp);
- samp += nspfr;
- if (par_file)
- {
- for (j=0; j < nEparm; j++)
- fprintf(par_file, " %6.4g", tp[j]);
- fprintf(par_file,"\n");
- }
- }
- if (par_file)
- {int j;
- for (j=0; j < nEparm; j++)
- fprintf(par_file,"%c%6.4g",(j) ? ' ' : '#',end[j].v);
- fprintf(par_file,"\n");
- for (j=0; j < nEparm; j++)
- fprintf(par_file,"%c%6d",(j) ? ' ' : '#',end[j].t);
- fprintf(par_file,"\n");
- }
- }
- le = ce;
- }
- return (samp - samp_base);
- }
-
- int init_holmes(argc,argv)
- int argc;
- char *argv[];
- {char *par_name = NULL;
- argc = getargs(argc,argv,
- "p","",&par_name,
- "S", "%d", &speed,
- "K", "%lg", &frac,
- NULL);
- if (par_name)
- {
- par_file = fopen(par_name,"w");
- if (!par_file)
- perror(par_name);
- }
- return argc;
- }
-
- void term_holmes()
- {
- if (par_file)
- fclose(par_file);
- }
-